import { Request, HttpMethod, BodyType, ParamItem } from '../../models/request.model';
import { Response, ensureResponseInstance } from '../../models/response.model';
import { MessageService } from '../../services/message.service';
import { StorageService } from '../../services/storage.service';
import { formatResponseTime, prettyJson } from '../../utils/utils';

/**
 * 请求编辑器类
 * 负责处理请求的编辑和发送
 */
export class RequestEditor {
    // 表单元素
    private methodSelect: HTMLSelectElement;
    private urlInput: HTMLInputElement;
    private nameInput: HTMLInputElement;
    private sendButton: HTMLButtonElement;
    private saveButton: HTMLButtonElement;
    private bodyTypeSelect: HTMLSelectElement;
    private bodyEditor: HTMLDivElement;

    // 响应元素
    private statusCode: HTMLSpanElement;
    private responseTime: HTMLSpanElement;
    private responseBody: HTMLPreElement;
    private responseHeadersList: HTMLDivElement;

    // 参数和请求头元素
    private paramsList: HTMLDivElement;
    private headersList: HTMLDivElement;
    private addParamButton: HTMLButtonElement;
    private addHeaderButton: HTMLButtonElement;

    // 当前请求和响应
    private currentRequest: Request;
    private currentResponse: Response | null = null;
    
    // 完成回调
    private onRequestComplete: (() => void) | undefined;
    private onRequestSaved: (() => void) | undefined;

    /**
     * 构造函数
     * @param onRequestComplete 请求完成回调
     * @param onRequestSaved 请求保存回调
     */
    constructor(onRequestComplete?: () => void, onRequestSaved?: () => void) {
        // 初始化请求对象
        this.currentRequest = new Request({
            method: HttpMethod.GET,
            url: '',
            params: [],
            headers: [],
            bodyType: BodyType.NONE
        });
        
        this.onRequestComplete = onRequestComplete;
        this.onRequestSaved = onRequestSaved;

        // 获取DOM元素
        this.methodSelect = document.getElementById('method') as HTMLSelectElement;
        this.urlInput = document.getElementById('url') as HTMLInputElement;
        this.nameInput = document.getElementById('request-name') as HTMLInputElement;
        this.sendButton = document.getElementById('send-button') as HTMLButtonElement;
        this.saveButton = document.getElementById('save-button') as HTMLButtonElement;
        this.bodyTypeSelect = document.getElementById('body-type') as HTMLSelectElement;
        this.bodyEditor = document.getElementById('body-editor') as HTMLDivElement;

        this.statusCode = document.getElementById('status-code') as HTMLSpanElement;
        this.responseTime = document.getElementById('response-time') as HTMLSpanElement;
        this.responseBody = document.getElementById('response-body') as HTMLPreElement;
        this.responseHeadersList = document.getElementById('response-headers-list') as HTMLDivElement;

        this.paramsList = document.getElementById('params-list') as HTMLDivElement;
        this.headersList = document.getElementById('headers-list') as HTMLDivElement;
        this.addParamButton = document.getElementById('add-param') as HTMLButtonElement;
        this.addHeaderButton = document.getElementById('add-header') as HTMLButtonElement;

        this.setupEventListeners();
    }

    /**
     * 设置事件监听器
     */
    private setupEventListeners(): void {
        // 发送请求
        this.sendButton.addEventListener('click', () => this.sendRequest());
        
        // 保存请求
        this.saveButton.addEventListener('click', () => this.saveRequest());

        // 请求方法变更
        this.methodSelect.addEventListener('change', () => this.updateRequestMethod());

        // URL变更
        this.urlInput.addEventListener('input', () => this.updateRequestUrl());
        
        // 名称变更
        this.nameInput.addEventListener('input', () => this.updateRequestName());

        // 请求体类型变更
        this.bodyTypeSelect.addEventListener('change', () => this.updateBodyType());

        // 添加参数
        this.addParamButton.addEventListener('click', () => this.addParam());

        // 添加请求头
        this.addHeaderButton.addEventListener('click', () => this.addHeader());
    }

    /**
     * 加载请求到当前请求
     * @param request 请求对象
     */
    public loadRequest(request: Request): void {
        console.log('加载请求到编辑器:', request);
        
        // 克隆请求避免修改原始对象
        this.currentRequest = request.clone();
        
        // 添加常用请求头（如果不存在）
        this.ensureCommonHeaders();
        
        // 更新UI
        this.updateRequestUI();
        
        // 清空响应部分
        this.clearResponse();
    }
    
    /**
     * 确保存在常用请求头
     */
    private ensureCommonHeaders(): void {
        const commonHeaders = [
            { key: 'Content-Type', value: 'application/json' },
            { key: 'Accept', value: 'application/json, text/plain, */*' },
            { key: 'User-Agent', value: navigator.userAgent }
        ];
        
        // 检查是否有常用请求头，如果没有则添加（禁用状态）
        commonHeaders.forEach(header => {
            const exists = this.currentRequest.headers.some(h => 
                h.key.toLowerCase() === header.key.toLowerCase());
                
            if (!exists) {
                this.currentRequest.headers.push({
                    key: header.key,
                    value: header.value,
                    enabled: false // 默认禁用
                });
            }
        });
    }

    /**
     * 更新请求UI
     */
    private updateRequestUI(): void {
        // 更新请求方法
        this.methodSelect.value = this.currentRequest.method;

        // 更新URL
        this.urlInput.value = this.currentRequest.url;
        
        // 更新名称
        this.nameInput.value = this.currentRequest.name || '';

        // 更新参数
        this.updateParamsList();

        // 更新请求头
        this.updateHeadersList();

        // 更新请求体
        this.bodyTypeSelect.value = this.currentRequest.bodyType;
        this.updateBodyEditor();
    }

    /**
     * 更新参数列表
     */
    private updateParamsList(): void {
        // 清空列表
        this.paramsList.innerHTML = '';

        // 添加参数
        this.currentRequest.params.forEach((param, index) => {
            const paramRow = this.createParamRow(param, index, 'param');
            this.paramsList.appendChild(paramRow);
        });
    }

    /**
     * 更新请求头列表
     */
    private updateHeadersList(): void {
        // 清空列表
        this.headersList.innerHTML = '';

        // 添加请求头
        this.currentRequest.headers.forEach((header, index) => {
            const headerRow = this.createParamRow(header, index, 'header');
            this.headersList.appendChild(headerRow);
        });
    }

    /**
     * 创建参数或请求头行
     * @param item 参数或请求头项
     * @param index 索引
     * @param type 类型（param或header）
     * @returns 行元素
     */
    private createParamRow(item: ParamItem, index: number, type: 'param' | 'header'): HTMLDivElement {
        const row = document.createElement('div');
        row.className = type === 'param' ? 'param-row' : 'header-row';

        // 添加启用复选框
        const checkboxCell = document.createElement('div');
        checkboxCell.className = 'checkbox-cell';
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = item.enabled;
        checkbox.addEventListener('change', () => {
            if (type === 'param') {
                this.currentRequest.params[index].enabled = checkbox.checked;
            } else {
                this.currentRequest.headers[index].enabled = checkbox.checked;
            }
        });
        checkboxCell.appendChild(checkbox);
        row.appendChild(checkboxCell);

        // 添加键输入框
        const keyCell = document.createElement('div');
        keyCell.className = 'key-cell';
        const keyInput = document.createElement('input');
        keyInput.type = 'text';
        keyInput.value = item.key;
        keyInput.placeholder = type === 'param' ? '参数名' : '请求头名';
        keyInput.addEventListener('input', () => {
            if (type === 'param') {
                this.currentRequest.params[index].key = keyInput.value;
            } else {
                this.currentRequest.headers[index].key = keyInput.value;
            }
        });
        keyCell.appendChild(keyInput);
        row.appendChild(keyCell);

        // 添加值输入框
        const valueCell = document.createElement('div');
        valueCell.className = 'value-cell';
        const valueInput = document.createElement('input');
        valueInput.type = 'text';
        valueInput.value = item.value;
        valueInput.placeholder = type === 'param' ? '参数值' : '请求头值';
        valueInput.addEventListener('input', () => {
            if (type === 'param') {
                this.currentRequest.params[index].value = valueInput.value;
            } else {
                this.currentRequest.headers[index].value = valueInput.value;
            }
        });
        valueCell.appendChild(valueInput);
        row.appendChild(valueCell);

        // 添加删除按钮
        const actionCell = document.createElement('div');
        actionCell.className = 'action-cell';
        const deleteButton = document.createElement('button');
        deleteButton.innerHTML = '&times;';
        deleteButton.title = '删除';
        deleteButton.addEventListener('click', () => {
            if (type === 'param') {
                this.currentRequest.params.splice(index, 1);
                this.updateParamsList();
            } else {
                this.currentRequest.headers.splice(index, 1);
                this.updateHeadersList();
            }
        });
        actionCell.appendChild(deleteButton);
        row.appendChild(actionCell);

        return row;
    }

    /**
     * 更新请求体编辑器
     */
    private updateBodyEditor(): void {
        // 清空编辑器
        this.bodyEditor.innerHTML = '';

        // 根据请求体类型创建不同的编辑器
        switch (this.currentRequest.bodyType) {
            case BodyType.NONE:
                // 无请求体
                const noneMessage = document.createElement('div');
                noneMessage.className = 'body-none-message';
                noneMessage.textContent = '此请求没有请求体';
                this.bodyEditor.appendChild(noneMessage);
                break;

            case BodyType.FORM_DATA:
            case BodyType.URLENCODED:
                // 创建表单编辑器
                const formContainer = document.createElement('div');
                formContainer.className = 'form-container';
                
                // 添加表头
                const headerRow = document.createElement('div');
                headerRow.className = 'form-row header-row';
                
                const checkboxCell = document.createElement('div');
                checkboxCell.className = 'checkbox-cell';
                checkboxCell.innerHTML = '<input type="checkbox" checked>';
                headerRow.appendChild(checkboxCell);
                
                const keyCell = document.createElement('div');
                keyCell.className = 'key-cell';
                keyCell.textContent = '键';
                headerRow.appendChild(keyCell);
                
                const valueCell = document.createElement('div');
                valueCell.className = 'value-cell';
                valueCell.textContent = '值';
                headerRow.appendChild(valueCell);
                
                const actionCell = document.createElement('div');
                actionCell.className = 'action-cell';
                headerRow.appendChild(actionCell);
                
                formContainer.appendChild(headerRow);
                
                // 添加表单项容器
                const formItemsContainer = document.createElement('div');
                formItemsContainer.className = 'form-items-container';
                formContainer.appendChild(formItemsContainer);

                // 添加表单项
                const formItems = (this.currentRequest.body as ParamItem[]) || [];
                formItems.forEach((item, index) => {
                    const formRow = this.createFormItemRow(item, index);
                    formItemsContainer.appendChild(formRow);
                });

                // 添加按钮
                const addButton = document.createElement('button');
                addButton.className = 'add-button';
                addButton.textContent = '添加表单项';
                addButton.addEventListener('click', () => {
                    if (!Array.isArray(this.currentRequest.body)) {
                        this.currentRequest.body = [];
                    }

                    (this.currentRequest.body as ParamItem[]).push({
                        key: '',
                        value: '',
                        enabled: true
                    });

                    this.updateBodyEditor();
                });
                formContainer.appendChild(addButton);

                this.bodyEditor.appendChild(formContainer);
                break;

            case BodyType.RAW:
                // 创建文本编辑器容器
                const editorContainer = document.createElement('div');
                editorContainer.className = 'raw-editor-container';
                
                // 添加格式选择器
                const formatSelector = document.createElement('div');
                formatSelector.className = 'raw-format-selector';
                
                const formats = [
                    { value: 'text', label: 'Text' },
                    { value: 'json', label: 'JSON' },
                    { value: 'xml', label: 'XML' },
                    { value: 'html', label: 'HTML' }
                ];
                
                formats.forEach(format => {
                    const formatButton = document.createElement('button');
                    formatButton.className = 'format-button';
                    formatButton.textContent = format.label;
                    formatButton.dataset.format = format.value;
                    
                    // 设置默认格式
                    if ((this.currentRequest.rawFormat || 'json') === format.value) {
                        formatButton.classList.add('active');
                    }
                    
                    formatButton.addEventListener('click', () => {
                        // 更新选中状态
                        formatSelector.querySelectorAll('.format-button').forEach(btn => {
                            btn.classList.remove('active');
                        });
                        formatButton.classList.add('active');
                        
                        // 保存格式
                        this.currentRequest.rawFormat = format.value;
                        
                        // 应用样式
                        textarea.className = `raw-editor ${format.value}-editor`;
                    });
                    
                    formatSelector.appendChild(formatButton);
                });
                
                editorContainer.appendChild(formatSelector);
                
                // 创建文本编辑器
                const textarea = document.createElement('textarea');
                textarea.className = `raw-editor ${this.currentRequest.rawFormat || 'json'}-editor`;
                textarea.value = this.currentRequest.body as string || '';
                textarea.placeholder = '请输入请求体内容';
                textarea.addEventListener('input', () => {
                    this.currentRequest.body = textarea.value;
                });
                
                // 设置初始高度
                textarea.style.height = '200px';
                
                // 自动调整高度
                textarea.addEventListener('input', function() {
                    this.style.height = 'auto';
                    this.style.height = (this.scrollHeight) + 'px';
                });
                
                editorContainer.appendChild(textarea);
                this.bodyEditor.appendChild(editorContainer);
                
                // 如果是JSON格式，提供格式化按钮
                if ((this.currentRequest.rawFormat || 'json') === 'json') {
                    const formatJsonButton = document.createElement('button');
                    formatJsonButton.className = 'format-json-button';
                    formatJsonButton.textContent = '格式化JSON';
                    formatJsonButton.addEventListener('click', () => {
                        try {
                            const jsonObj = JSON.parse(textarea.value);
                            textarea.value = JSON.stringify(jsonObj, null, 2);
                            this.currentRequest.body = textarea.value;
                            // 自动调整高度
                            textarea.style.height = 'auto';
                            textarea.style.height = (textarea.scrollHeight) + 'px';
                        } catch (e) {
                            this.showNotification('无效的JSON格式', 'error');
                        }
                    });
                    this.bodyEditor.appendChild(formatJsonButton);
                }
                break;

            case BodyType.BINARY:
                // 创建文件选择器容器
                const fileContainer = document.createElement('div');
                fileContainer.className = 'file-upload-container';
                
                // 创建标签
                const fileLabel = document.createElement('label');
                fileLabel.className = 'file-upload-label';
                fileLabel.innerHTML = '选择文件';
                
                // 创建文件选择器
                const fileInput = document.createElement('input');
                fileInput.type = 'file';
                fileInput.className = 'file-upload-input';
                fileInput.addEventListener('change', () => {
                    if (fileInput.files && fileInput.files.length > 0) {
                        this.currentRequest.body = fileInput.files[0];
                        fileInfoText.textContent = `已选择：${fileInput.files[0].name} (${this.formatFileSize(fileInput.files[0].size)})`;
                    }
                });
                
                fileLabel.appendChild(fileInput);
                fileContainer.appendChild(fileLabel);
                
                // 文件信息显示
                const fileInfoText = document.createElement('div');
                fileInfoText.className = 'file-info';
                fileInfoText.textContent = '未选择文件';
                fileContainer.appendChild(fileInfoText);
                
                this.bodyEditor.appendChild(fileContainer);
                break;
        }
    }
    
    /**
     * 格式化文件大小
     */
    private formatFileSize(bytes: number): string {
        if (bytes < 1024) {
            return bytes + ' B';
        } else if (bytes < 1024 * 1024) {
            return (bytes / 1024).toFixed(2) + ' KB';
        } else if (bytes < 1024 * 1024 * 1024) {
            return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
        } else {
            return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
        }
    }
    
    /**
     * 创建表单项行元素
     */
    private createFormItemRow(item: ParamItem, index: number): HTMLDivElement {
        const row = document.createElement('div');
        row.className = 'form-row';

        // 添加启用复选框
        const checkboxCell = document.createElement('div');
        checkboxCell.className = 'checkbox-cell';
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = item.enabled;
        checkbox.addEventListener('change', () => {
            if (Array.isArray(this.currentRequest.body)) {
                (this.currentRequest.body as ParamItem[])[index].enabled = checkbox.checked;
            }
        });
        checkboxCell.appendChild(checkbox);
        row.appendChild(checkboxCell);

        // 添加键输入框
        const keyCell = document.createElement('div');
        keyCell.className = 'key-cell';
        const keyInput = document.createElement('input');
        keyInput.type = 'text';
        keyInput.value = item.key;
        keyInput.placeholder = '参数名';
        keyInput.addEventListener('input', () => {
            if (Array.isArray(this.currentRequest.body)) {
                (this.currentRequest.body as ParamItem[])[index].key = keyInput.value;
            }
        });
        keyCell.appendChild(keyInput);
        row.appendChild(keyCell);

        // 添加值输入框
        const valueCell = document.createElement('div');
        valueCell.className = 'value-cell';
        const valueInput = document.createElement('input');
        valueInput.type = 'text';
        valueInput.value = item.value;
        valueInput.placeholder = '参数值';
        valueInput.addEventListener('input', () => {
            if (Array.isArray(this.currentRequest.body)) {
                (this.currentRequest.body as ParamItem[])[index].value = valueInput.value;
            }
        });
        valueCell.appendChild(valueInput);
        row.appendChild(valueCell);

        // 添加删除按钮
        const actionCell = document.createElement('div');
        actionCell.className = 'action-cell';
        const deleteButton = document.createElement('button');
        deleteButton.innerHTML = '&times;';
        deleteButton.title = '删除';
        deleteButton.addEventListener('click', () => {
            if (Array.isArray(this.currentRequest.body)) {
                (this.currentRequest.body as ParamItem[]).splice(index, 1);
                this.updateBodyEditor();
            }
        });
        actionCell.appendChild(deleteButton);
        row.appendChild(actionCell);

        return row;
    }

    /**
     * 更新请求方法
     */
    private updateRequestMethod(): void {
        this.currentRequest.method = this.methodSelect.value as HttpMethod;
    }

    /**
     * 更新请求URL
     */
    private updateRequestUrl(): void {
        this.currentRequest.url = this.urlInput.value;
    }
    
    /**
     * 更新请求名称
     */
    private updateRequestName(): void {
        this.currentRequest.name = this.nameInput.value;
    }

    /**
     * 更新请求体类型
     */
    private updateBodyType(): void {
        this.currentRequest.bodyType = this.bodyTypeSelect.value as BodyType;

        // 重置请求体
        switch (this.currentRequest.bodyType) {
            case BodyType.NONE:
                this.currentRequest.body = undefined;
                break;

            case BodyType.FORM_DATA:
            case BodyType.URLENCODED:
                this.currentRequest.body = [];
                break;

            case BodyType.RAW:
                this.currentRequest.body = '';
                break;

            case BodyType.BINARY:
                this.currentRequest.body = undefined;
                break;
        }

        // 更新UI
        this.updateBodyEditor();
    }

    /**
     * 添加参数
     */
    private addParam(): void {
        this.currentRequest.params.push({
            key: '',
            value: '',
            enabled: true
        });

        this.updateParamsList();
    }

    /**
     * 添加请求头
     */
    private addHeader(): void {
        this.currentRequest.headers.push({
            key: '',
            value: '',
            enabled: true
        });

        this.updateHeadersList();
    }

    /**
     * 发送请求
     */
    public async sendRequest(): Promise<void> {
        try {
            // 显示加载状态
            this.sendButton.disabled = true;
            this.sendButton.textContent = '发送中...';

            // 清空响应
            this.statusCode.textContent = '';
            this.responseTime.textContent = '';
            this.responseBody.textContent = '';
            this.responseHeadersList.innerHTML = '';

            // 发送请求
            const result = await MessageService.sendRequest(this.currentRequest);

            if (result && result.success && result.response) {
                // 更新响应，确保是Response实例
                this.currentResponse = ensureResponseInstance(result.response);
                this.updateResponseUI();
            } else {
                // 显示错误
                this.statusCode.textContent = '错误';
                this.statusCode.className = 'status-code error';
                this.responseBody.textContent = result.error || '发送请求失败';
            }
        } catch (error) {
            console.error('Error sending request:', error);

            // 显示错误
            this.statusCode.textContent = '错误';
            this.statusCode.className = 'status-code error';
            this.responseBody.textContent = String(error);
        } finally {
            // 恢复按钮状态
            this.sendButton.disabled = false;
            this.sendButton.textContent = '发送';
            
            // 调用完成回调
            if (this.onRequestComplete) {
                this.onRequestComplete();
            }
        }
    }

    /**
     * 更新响应UI
     */
    private updateResponseUI(): void {
        if (!this.currentResponse) return;

        // 确保响应对象具有正确的原型链
        const response = ensureResponseInstance(this.currentResponse);

        // 设置状态码
        this.statusCode.textContent = `${response.status} ${response.statusText}`;
        this.statusCode.className = response.isSuccess() ? 'status-code success' : 'status-code error';

        // 设置响应时间
        this.responseTime.textContent = formatResponseTime(response.time);

        // 设置响应体
        this.responseBody.textContent = response.formatBody();

        // 设置响应头
        this.responseHeadersList.innerHTML = '';
        Object.entries(response.headers).forEach(([name, value]) => {
            const headerItem = document.createElement('div');
            headerItem.className = 'header-item';

            const headerName = document.createElement('div');
            headerName.className = 'header-name';
            headerName.textContent = name;
            headerItem.appendChild(headerName);

            const headerValue = document.createElement('div');
            headerValue.className = 'header-value';
            headerValue.textContent = value;
            headerItem.appendChild(headerValue);

            this.responseHeadersList.appendChild(headerItem);
        });
    }

    /**
     * 保存请求
     */
    private async saveRequest(): Promise<void> {
        try {
            console.log('正在保存请求:', this.currentRequest);
            
            // 检查必填字段
            if (!this.currentRequest.url) {
                this.showNotification('请输入URL', 'error');
                return;
            }
            
            // 如果没有设置名称，使用默认名称
            if (!this.currentRequest.name || this.currentRequest.name.trim() === '') {
                this.currentRequest.name = `${this.currentRequest.method} ${this.currentRequest.url}`;
                this.nameInput.value = this.currentRequest.name;
            }
            
            // 保存请求
            await StorageService.saveRequest(this.currentRequest);
            
            // 显示成功提示
            this.showNotification('请求已保存', 'success');
            
            // 调用保存回调
            if (this.onRequestSaved) {
                this.onRequestSaved();
            }
        } catch (error) {
            console.error('保存请求时出错:', error);
            this.showNotification('保存请求失败', 'error');
        }
    }
    
    /**
     * 显示通知提示
     * @param message 提示消息
     * @param type 提示类型
     */
    private showNotification(message: string, type: 'success' | 'error'): void {
        // 检查是否已存在通知元素
        let notification = document.getElementById('notification');
        if (!notification) {
            // 创建通知元素
            notification = document.createElement('div');
            notification.id = 'notification';
            document.body.appendChild(notification);
        }
        
        // 设置样式和消息
        notification.className = `notification ${type}`;
        notification.textContent = message;
        
        // 显示通知
        notification.classList.add('show');
        
        // 3秒后自动隐藏
        setTimeout(() => {
            notification.classList.remove('show');
        }, 3000);
    }

    /**
     * 清空响应部分
     */
    private clearResponse(): void {
        this.currentResponse = null;
        this.statusCode.textContent = '';
        this.responseTime.textContent = '';
        this.responseBody.textContent = '';
        this.responseHeadersList.innerHTML = '';
    }
} 